/*
    Copyright 2024, Haiku, Inc. All Rights Reserved.
    Distributed under the terms of the MIT License.

    龙芯7A2000 GPU驱动接口定义
*/

#ifndef DRIVERINTERFACE_H
#define DRIVERINTERFACE_H

#include <Accelerant.h>
#include "video_overlay.h"
#include <Drivers.h>
#include <PCI.h>
#include <OS.h>
#include "AGP.h"

#define DRIVER_PREFIX "loongson7a"

/*
    Internal driver state (also for sharing info between driver and accelerant)
*/
#if defined(__cplusplus)
extern "C"
{
#endif

    typedef struct
    {
        sem_id sem;
        int32 ben;
    } benaphore;

#define INIT_BEN(x)                                 \
    x.sem = create_sem(0, "LS7A " #x " benaphore"); \
    x.ben = 0;
#define AQUIRE_BEN(x)                   \
    if ((atomic_add(&(x.ben), 1)) >= 1) \
        acquire_sem(x.sem);
#define RELEASE_BEN(x)                  \
    if ((atomic_add(&(x.ben), -1)) > 1) \
        release_sem(x.sem);
#define DELETE_BEN(x) delete_sem(x.sem);

#define LS7A_PRIVATE_DATA_MAGIC 0x7A20 /* 龙芯7A2000 GPU驱动私有数据标识 */

/* 双显示头标志位 */
#define DUALHEAD_OFF (0 << 6)
#define DUALHEAD_CLONE (1 << 6)
#define DUALHEAD_ON (2 << 6)
#define DUALHEAD_SWITCH (3 << 6)
#define DUALHEAD_BITS (3 << 6)
#define DUALHEAD_CAPABLE (1 << 8)

#define SKD_MOVE_CURSOR 0x00000001
#define SKD_PROGRAM_CLUT 0x00000002
#define SKD_SET_START_ADDR 0x00000004
#define SKD_SET_CURSOR 0x00000008
#define SKD_HANDLER_INSTALLED 0x80000000

    enum
    {
        ENG_GET_PRIVATE_DATA = B_DEVICE_OP_CODES_END + 1,
        ENG_GET_PCI,
        ENG_SET_PCI,
        ENG_DEVICE_NAME,
        ENG_RUN_INTERRUPTS,
        ENG_GET_NTH_AGP_INFO,
        ENG_ENABLE_AGP,
        ENG_ISA_OUT,
        ENG_ISA_IN
    };

/* 最大叠加缓冲区数量 */
#define MAXBUFFERS 3

    /* 叠加缓冲区内部信息 */
    typedef struct
    {
        uint16 slopspace;
        uint32 size;
    } int_buf_info;

    typedef struct settings
    {
        // 驱动设置
        char accelerant[B_FILE_NAME_LENGTH];
        bool dumprom;
        // 加速器设置
        uint32 logmask;
        uint32 memory;
        bool usebios;
        bool hardcursor;
        bool switchhead;
        bool force_pci;
    } settings;

    /* 共享信息结构 */
    typedef struct
    {
        /* 设备标识信息 */
        uint16 vendor_id; /* PCI vendor ID */
        uint16 device_id; /* PCI device ID */
        uint8 revision;   /* PCI device revision */
        uint8 bus;        /* PCI bus number */
        uint8 device;     /* PCI device number on bus */
        uint8 function;   /* PCI function number in device */

        /* 4.5.0版本的bug修复 */
        uint32 use_clone_bugfix; /* 4.5.0版本中物理内存克隆不工作的修复 */
        uint32 *clone_bugfix_regs;

        /* 内存映射 */
        area_id regs_area; /* 内核中寄存器内存映射区域ID */

        area_id fb_area;         /* 帧缓冲区域ID，所有团队共享 */
        area_id pseudo_dma_area; /* 伪DMA区域ID，所有团队共享 */
        area_id dma_buffer_area; /* DMA缓冲区域ID */

        void *framebuffer;     /* 虚拟内存视图 */
        void *framebuffer_pci; /* PCI总线视图（用于DMA） */

        void *pseudo_dma; /* 虚拟内存视图 */

        void *dma_buffer;     /* DMA缓冲区 */
        void *dma_buffer_pci; /* PCI总线视图的DMA缓冲区 */

        /* 屏幕模式列表 */
        area_id mode_area; /* 包含驱动支持的显示模式列表 */
        uint32 mode_count; /* 列表中的显示模式数量 */

        /* 标志位 - 驱动使用 */
        uint32 flags;

        /* 垂直消隐信号量 */
        sem_id vblank; /* 垂直消隐信号量，所有权将转移给首先打开设备的团队 */

        /* 光标信息 */
        struct
        {
            uint16 hot_x; /* 光标热点，光标左上角为0,0 */
            uint16 hot_y;
            uint16 x; /* 桌面上光标热点的位置 */
            uint16 y;
            uint16 width; /* 光标形状的宽度和高度 */
            uint16 height;
            bool is_visible; /* 光标当前是否显示？ */
            bool dh_right;   /* 光标是否在拉伸屏幕的右侧？ */
        } cursor;

        /* 颜色查找表 */
        uint8 color_data[3 * 256]; /* 颜色查找表 - DAC使用 */

        /* 更多显示模式信息 */
        display_mode dm;       /* 当前显示模式配置：头1 */
        display_mode dm2;      /* 当前显示模式配置：头2 */
        bool acc_mode;         /* 信号（非）加速模式 */
        bool crtc_switch_mode; /* 使用面板时的双头切换模式信号 */

        /* 帧缓冲配置 - 用于BDirectScreen */
        frame_buffer_config fbc;  /* 每行字节数和帧缓冲起始位置：头1 */
        frame_buffer_config fbc2; /* 每行字节数和帧缓冲起始位置：头2 */

        /* 加速引擎 */
        struct
        {
            uint32 count;     /* 最后使用的dwgsync槽 */
            uint32 last_idle; /* 最后一个我们*知道*引擎空闲的dwgsync槽 */
            benaphore lock;   /* 用于序列化对加速引擎的访问 */
        } engine;

        /* 卡信息 - 从PINS（和其他来源）收集的信息 */
        struct
        {
            /* 卡初始化的专用寄存器 */

            /* 一般卡信息 */
            bool secondary_head; /* 功能存在 */
            bool primary_dvi;
            bool secondary_dvi;
            uint32 memory_size; /* 内存（字节） */

            /* 时钟限制 */
            float f_ref;             /* PLL参考振荡器频率（MHz） */
            uint32 max_pixel_clock;  /* 最大像素时钟（MHz） */
            uint32 max_memory_clock; /* 最大内存时钟（MHz） */
            uint32 max_engine_clock; /* 最大引擎时钟（MHz） */
        } ps;

        /* 配置设置 */
        settings settings;

        struct
        {
            overlay_buffer myBuffer[MAXBUFFERS]; /* 缩放器输入缓冲区 */
            int_buf_info myBufInfo[MAXBUFFERS];  /* 缩放器输入缓冲区的额外信息 */
            overlay_token myToken;               /* 缩放器空闲/使用中 */
            benaphore lock;                      /* 用于创建缓冲区和获取叠加单元例程 */
            bool crtc;                           /* 叠加单元位置 */
            /* 虚拟屏幕所需的变量（move_overlay()）： */
            bool active;        /* 叠加当前是否使用中 */
            overlay_window ow;  /* 叠加输出窗口的当前位置 */
            overlay_buffer ob;  /* 当前使用的输入缓冲区 */
            overlay_view my_ov; /* 输入缓冲区中的当前校正视图 */
            uint32 h_ifactor;   /* 当前'未裁剪'水平反向缩放因子 */
            uint32 v_ifactor;   /* 当前'未裁剪'垂直反向缩放因子 */
        } overlay;

    } shared_info;

    /* 读取或写入PCI配置空间中的值 */
    typedef struct
    {
        uint32 magic;  /* 确保调用者理解我们的魔数 */
        uint32 offset; /* 要读取/写入的偏移量 */
        uint32 size;   /* 要传输的字节数 */
        uint32 value;  /* 读取或写入的值 */
    } eng_get_set_pci;

    /* 设置某些布尔条件（如启用或禁用中断） */
    typedef struct
    {
        uint32 magic; /* 确保调用者理解我们的魔数 */
        bool do_it;   /* 要设置的状态 */
    } eng_set_bool_state;

    /* 检索内核/加速器共享信息的area_id */
    typedef struct
    {
        uint32 magic;             /* 确保调用者理解我们的魔数 */
        area_id shared_info_area; /* 包含共享信息的area_id */
    } eng_get_private_data;

    /* 检索设备名称。当我们有文件句柄但想知道设备名称时很有用（如克隆加速器时） */
    typedef struct
    {
        uint32 magic; /* 确保调用者理解我们的魔数 */
        char *name;   /* 设备名称，减去/dev根 */
    } eng_device_name;

    /* 如果存在，检索AGP设备接口。用于查找使用的AGP速度方案（pre 3.x或3.x） */
    typedef struct
    {
        uint32 magic;  /* 确保调用者理解我们的魔数 */
        bool agp_bus;  /* 指示我们是否有权访问AGP总线管理器 */
        uint8 index;   /* 设备在找到的设备列表中的索引 */
        bool exist;    /* 我们获得了AGP设备信息 */
        agp_info agpi; /* 设备的AGP接口信息 */
    } eng_nth_agp_info;

    /* 执行AGP命令 */
    typedef struct
    {
        uint32 magic; /* 确保调用者理解我们的魔数 */
        bool agp_bus; /* 指示我们是否有权访问AGP总线管理器 */
        uint32 cmd;   /* 要执行的实际命令 */
    } eng_cmd_agp;

    /* 读取或写入ISA I/O空间中的值 */
    typedef struct
    {
        uint32 magic;  /* 确保调用者理解我们的魔数 */
        uint16 adress; /* 要读取/写入的偏移量 */
        uint8 size;    /* 要传输的字节数 */
        uint16 data;   /* 读取或写入的值 */
    } eng_in_out_isa;

    enum
    {

        _WAIT_FOR_VBLANK = (1 << 0)
    };

#if defined(__cplusplus)
}
#endif

#endif